/**
 * jQuery comet
 *
 * Copyright (c) 2011 Zhao Yong (7tudou@gmail.com)
 *
 * @version 1.0.0
 * @author Zhao Yong
 * @mailto 7tudou@gmail.com
 * @modify Zhao Yong
 * @edit by Zhao Yong add if link fail . Private information
 **/

var JSON;if(!JSON){JSON={};}
(function(){"use strict";function f(n){return n<10?'0'+n:n;}
if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+
f(this.getUTCMonth()+1)+'-'+
f(this.getUTCDate())+'T'+
f(this.getUTCHours())+':'+
f(this.getUTCMinutes())+':'+
f(this.getUTCSeconds())+'Z':null;};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf();};}
var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4);})+'"':'"'+string+'"';}
function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key);}
if(typeof rep==='function'){value=rep.call(holder,key,value);}
switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null';}
gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||'null';}
v=partial.length===0?'[]':gap?'[\n'+gap+partial.join(',\n'+gap)+'\n'+mind+']':'['+partial.join(',')+']';gap=mind;return v;}
if(rep&&typeof rep==='object'){length=rep.length;for(i=0;i<length;i+=1){if(typeof rep[i]==='string'){k=rep[i];v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}else{for(k in value){if(Object.prototype.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}
v=partial.length===0?'{}':gap?'{\n'+gap+partial.join(',\n'+gap)+'\n'+mind+'}':'{'+partial.join(',')+'}';gap=mind;return v;}}
if(typeof JSON.stringify!=='function'){JSON.stringify=function(value,replacer,space){var i;gap='';indent='';if(typeof space==='number'){for(i=0;i<space;i+=1){indent+=' ';}}else if(typeof space==='string'){indent=space;}
rep=replacer;if(replacer&&typeof replacer!=='function'&&(typeof replacer!=='object'||typeof replacer.length!=='number')){throw new Error('JSON.stringify');}
return str('',{'':value});};}
if(typeof JSON.parse!=='function'){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==='object'){for(k in value){if(Object.prototype.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v;}else{delete value[k];}}}}
return reviver.call(holder,key,value);}
text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return'\\u'+
('0000'+a.charCodeAt(0).toString(16)).slice(-4);});}
if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){j=eval('('+text+')');return typeof reviver==='function'?walk({'':j},''):j;}
throw new SyntaxError('JSON.parse');};}}());


var G = {};
var P = {};
$.CL = {};
$.UT = {};
G.PopOpenList = []; //当前弹出窗口列表;
G.PupExpandList = []; //当前临时层列表;
G.RequestQueue = {}; //远程请求队列；
G.RequestTimmer = 0; //远程请求定时器；
G.AutoNumber = 0; //自动累加编号；
G.LoadingCss = "g-loading-on";
G.GlobalLoading = "<div pclass='g-loading' style='display:none;top:0;left:0'>Loadding...</div>";
G.GlobalLoadingCounter = 0;
G.ResultSplitChar = "êêê";
G.LanguageMapping = {
	duplicate_definition_property_module: "Module属性不能被占用！",
	duplicate_definition_property_class: "类名属性不能被占用！"
};
P.Mod = {};
P.Utl = {};
P.Set = {};

/* AJAX初始定义 */
$.ajaxSetup({
    cache: false,
    global: false,
    beforeSend: function (x) {
        x.setRequestHeader("ajax", "true");
    }
});

/* Fix to Improve IE6 */
if (document.uniqueID && !window.XMLHttpRequest) {
    try {
        document.execCommand('BackgroundImageCache', false, true);
    } catch (e) { }
}
/* 弹出窗口响应window.sizeChange事件 */
$(window).bind('sizeChange', function (e, d) {
    var i, o;
    for (i = 0; i < G.PopOpenList.length; i++) {
        o = G.PopOpenList[i];
        o.refreshPos();
    }
});

/* 合并window.resize事件 */
(function () {
    var resizeTimer;
    window.onresize = function () {
        if (!resizeTimer) {
            resizeTimer = setTimeout(function () {
                resizeTimer = 0;
                $(window).triggerHandler('sizeChange', {clientHeight:document.documentElement.clientHeight,clientWidth:document.documentElement.clientWidth});
            }, 1000);
        }
    };
}());

$(document).ready(function(){
    /* 临时弹层的响应关闭 */
    $(document.body).bind("mousedown", function (e) {
        var i, o;
        for (i in G.PupExpandList) {
            o = G.PupExpandList[i];
            if (!$.UT.InContainer(e.target, o.dom[0])) {
                o.close();
            } else {
                return true;
            }
        }
        G.PupExpandList = [];
    });
});

$.CL.Request = function(opts){
    this.cnet = "ajax"; //请求类型。取值："ajax","iframe"
    this.module = "index"; //模组id
    this.action = "init"; //action id
    this.url = ""; //远程地址
    this.post = null; //post数据
    this.get = null; //get数据
    this.successCallback = $.UT.DefaultSuccessCallback; //成功回调
    this.errorCallback = $.UT.DefaultErrorCallback; //失败回调
    this.cache = false; //是否缓存
    this.timeout = 20000; //超时设置
    this.timeoutTimer = 0; //超时侦测器
    this.timeBegin = 0;
    this.iframe = null; //指定的iframe 目标，仅用于cnet为iframe，若为空则动态创建
    this.iform = null; //指定的form 目标，仅用于cnet为iframe，若为空则动态创建
    this.net = null; //连接引用
    this.netForm = null;
    this.button = null; //触发请求的button，用于变色与防重复提交
    this.merge = {}; //合并请求
    this.mergeKey = "";
    if(opts){$.extend(this, opts);}
};
$.CL.Request.prototype = {
    resultCall: function(result){
        var i,arr=[];
        if(this.timeoutTimer){clearInterval(this.timeoutTimer);}
        if (result.state) {
            if(this.mergeKey === ""){
                this.successCallback(result.data, result.attach);
            }else{
                this.successCallback(result.data[this.mergeKey], result.attach);
            }
            arr = [this.successCallback];
            for(i in this.merge){
                var icall = this.merge[i].successCallback;
                if($.inArray(icall, arr) == -1){
                    arr.push(icall);
                    icall(result.data[i], result.attach);
                }
            }
        } else {
            this.errorCallback(result.errors, result.data);
            arr = [this.errorCallback];
            for(i in this.merge){
                var icall = this.merge[i].errorCallback;
                if($.inArray(icall, arr) == -1){
                    arr.push(icall);
                    icall(result.errors, result.data);
                }
            }
        }
    },
    abort: function (passAll) {
        if(this.timeoutTimer){clearInterval(this.timeoutTimer);}
        if(passAll){
            this.successCallback = function (data) { };
            this.errorCallback = function (data) { };
        }
        if(this.net){
            if (this.net.abort) {
                this.net.abort();
            } else {
                this.net.src = "about:blank";
                $(this.net).triggerHandler('abort');
            }
        }
    }
};

$.CL.Result = function(o){
    this.state = 0;
    this.data = '';
    this.errors = null;
    this.attach = [];
    this.source = o;
    if(o){this.decode(o);}
};
$.CL.Result.prototype = {
    setErrors: function (errors, data) {
        var i, error;
        this.state = 0;
        this.data = "";
        this.errors = {};
        for (i in errors) {
            error = errors[i];
            if (error.nid != '') {
                error.eid = P.Set.ErrorMapping[error.nid][error.eid];
                error.nid = '';
            }
            this.errors[error.eid] = error;
        }
    },
    decode: function (str) {
        var boundary = G.ResultSplitChar;
        var arr = str.split(boundary);
        var json = $.UT.JsonDecode(arr[0]);
        arr.shift();
        if(!json || !json.hasOwnProperty("state")){
            this.setErrors([{nid:'framework', eid:'resultDecodeError', file:'$.CL.Result', line:0 , note:str}]);
            return false;
        }
        json.state = Number(json.state);
        if(!json.state){
            var errors = {};
            var i;
            for(i in json.errors){
                var error = json.errors[i];
                error.eid = P.Set.ErrorMapping[error.nid][error.eid];
                errors[error.eid] = error;
            }
        }
        this.state = json.state;
        this.data = json.data;
        this.errors = errors;
        this.attach = arr;
    }
};

$.CL.Dialog = function (dom, opts) {
    var s, win, _this = this, doms;
    dom = $(dom);
    if (!dom[0]) { return false; }
    if (dom.data("Dialog")) { return false; }
    this.dom = dom;
    this.options = { mask: true, cssClass:"", title:"Dialog", offset:{left:0,top:0}, region:document.body, resize:false, normalWidth:0, normalHeight:0, button:null, maskRender:'<div class="g-dialog-mask"><!--[if lte IE 6.5]><iframe style="position:absolute;top:0;left:0;z-index:-1;width:100%;height:100%;filter:mask();"></iframe><![endif]--></div>', windowRender:'<div class="g-dialog-win"><div class="pop-border"><div dom="head" class="pop-hd"><h4 dom="title"></h4><a href="#" dom="close" class="close"><a href="#" dom="toggleSize" class="maxsize"></a></div><div class="pop-bd"><div dom="container" class="pop-container"></div></div><div class="pop-ft"></div></div></div>' };
    $.extend(this.options, opts);
    this.options.cssClass = dom.attr("pclass") || this.options.cssClass;
    this.options.title = dom.attr("ptitle") || this.options.title;
    this.options.normalWidth = dom.attr("normal-width") || this.options.normalWidth;
    this.options.normalHeight = dom.attr("normal-height") || this.options.normalHeight;
    dom.css("display", "block");
    if (this.options.mask) {
        this.mask = $(this.options.maskRender).appendTo(document.body);
        this.mask.addClass(this.options.cssClass);
    }
    this.window = $(this.options.windowRender).appendTo(document.body);
    this.window.css("display", "none");
    doms = $.UT.DomSelector($("*",this.window));
    this.container = $(doms.container);
    this.container.append(dom);
    this.head = $(doms.head);
    this.title = $(doms.title);
    this.body = dom;
    this.toggleSizeBtn = $(doms.toggleSize);
    this.toggleSize = 0;
    this.closeBtn = $(doms.close);
    this.openData = null;
    this.region = null;
    this.title.html(this.options.title);
    this.window.addClass(this.options.cssClass);
    this.setResizeAble(this.options.resize, this.options.normalWidth, this.options.normalHeight);
    this.closeBtn.click(function (e) { _this.close(); return false; });
    this.toggleSizeBtn.click(function (e) { _this.toggleSize(); return false; });
    //this.window.draggable({ handle: this.head });
    dom.data("Dialog", this);
};
$.CL.Dialog.prototype = {
    setResizeAble: function(able, normalWidth, normalHeight){
        this.options.resize = able;
        this.options.normalWidth = Number(normalWidth);
        this.options.normalHeight = Number(normalHeight);
        if(able){
            this.toggleSizeBtn.show();
            this.container[0].style.width = this.options.normalWidth + "px";
            this.container[0].style.height = this.options.normalHeight + "px";
        }else{
            this.toggleSizeBtn.hide();
        }
    },
    setCssClass: function(cl){
        if(cl){
            this.window.removeClass(this.options.cssClass);
            this.mask.removeClass(this.options.cssClass);
            this.options.cssClass = cl;
            this.window.addClass(cl);
            this.mask.addClass(cl);
            this.windowPos = {paddingWidth:this.window.width()-this.container.width(), paddingHeight:this.window.height()-this.container.height()};
        }
    },
    getContent: function () {
        var moduleLoader = (this.body.data("ModuleLoader")) ? this.body.data("ModuleLoader") : null;
        if (moduleLoader && moduleLoader.module) {
            return moduleLoader.module.dom;
        } else {
            return this.body;
        }
    },
    setNormalSize : function(){
        this.window.removeClass("maxsize");
        this.window.addClass("normalsize");
        this.toggleSize = 0;
        if(this.options.normalWidth){this.container[0].style.width = this.options.normalWidth + "px";}
        if(this.options.normalHeight){this.container[0].style.height = this.options.normalHeight + "px";}
        if (!this.options.button) {
            this.setCenter();
        } else if(this.options.button != "invalid"){
            this.setFollow();
        }else{
            this.setFixed();
        }
    },
    setMaxSize : function(){
        this.window.removeClass("normalsize");
        this.window.addClass("maxsize");
        this.toggleSize = 1;
        this.window[0].style.left = 0;
        this.window[0].style.top = 0;
        this.container[0].style.width = document.documentElement.clientWidth - this.windowPos.paddingWidth + 'px';
        this.container[0].style.height = document.documentElement.clientHeight - this.windowPos.paddingHeight + 'px';
    },
    toggleSize: function(){
        if(this.toggleSize){
            this.setNormalSize();
        }else{
            setMaxSize();
        }
    },
    open: function (button, mask, data, offset, refresh) {
        var w, w2, ppos, pos, left, index, len, pop;
        if (this.isOpen() && !refresh) { return true;}// && this.toggleSize
        if(mask === undefined){mask = this.options.mask;}
        if(button !== undefined){
            button = $(button);
            if(button[0]){ this.options.button = button;}else{this.options.button = "invalid";}
        }
        if(offset){
            this.options.offset = offset;
        }
        this.openData = data;
        len = G.PopOpenList.length;
        if (len == 0) {
            index = 1000;
        } else {
            pop = G.PopOpenList[len - 1];
            index = Number(pop.window.css("zIndex"));
            index = (index) ? index : (1000 + len * 2);
        }
        index++;
        if (this.mask) {
            if(mask){
                this.mask[0].style.zIndex = index;
                this.mask[0].style.display = "block";
            }else{
                this.mask[0].style.display = "none";
            }
        }
        this.window[0].style.zIndex = index + 1;
        this.toggleSize = 0;
        this.refreshPos();
        this.window.show();
        G.PopOpenList.push(this);
        this.getContent().triggerHandler('open', data, this);        
    },
    _setMaskSize: function(){
        if(this.options.mask){
            this.mask[0].style.height = (document.body.offsetHeight < document.documentElement.clientHeight) ? document.documentElement.clientHeight + "px" : document.body.offsetHeight + "px"; 
        }
    },
    setTitle: function(str){
        if(str == null){
            str = this.getContent().attr("ptitle");
        }
        if(str != null){
            this.options.title = str;
            this.title.html(str);
        }
    },
    setCenter: function () {
        this.window[0].style.position = "absolute";
        this.window[0].style.left = (document.documentElement.clientWidth - this.window.width()) / 2 + 'px';
        this.window[0].style.top = (document.documentElement.clientHeight - this.window.height()) / 2 + document.documentElement.scrollTop + 'px';
    },
    _countRegion: function(){
        if(this.options.region){
            if(this.options.region.left){
                this.region = this.options.region;
            }else{
                this.region = $(this.options.region);
                var pos = this.region.offset();
                this.region = {left:pos.left, top:pos.top, right:pos.left+this.region.width(), bottom:pos.top+this.region.height()};
            }
        }else{
            this.region = null;
        }
    },
    setFixed: function () {
        this.window[0].style.position = "fixed";
        this.window[0].style.left = this.body[0].style.left;
        this.window[0].style.right = this.body[0].style.right;
        this.window[0].style.top = this.body[0].style.top;
        this.window[0].style.bottom = this.body[0].style.bottom;
    },
    setFollow: function () {
        if(this.region){
            this.window[0].style.position = "absolute";
            var pos = this.options.button.offset();
            pos.top = pos.top + this.options.button.height();
            pos.left = pos.left + this.options.offset.left;
            pos.top = pos.top  + this.options.offset.top;
            if(pos.left < this.region.left){pos.left = this.region.left;}
            if(pos.left > this.region.right){pos.left = this.region.right;}
            if(pos.top < this.region.top){pos.top = this.region.top;}
            if(pos.top > this.region.bottom){pos.top = this.region.bottom;}
            this.window[0].style.left = pos.left + 'px';
            this.window[0].style.top = pos.top + 'px';
        }
    },
    refreshPos: function () {
        this._countRegion();
        if (this.toggleSize) {
           this.setMaxSize();
        } else {
            this.setNormalSize();
        }
        this._setMaskSize();
    },
    close: function () {
        if (this.mask) {
            this.mask.hide();
        }
        this.window.hide();
        this.openData = null;
        var n = $.inArray(this, G.PopOpenList);
        if (n > -1) {
           G.PopOpenList.splice(n, 1);
        }
        this.getContent().triggerHandler('close');
    },
    isOpen: function () {
        return this.window.css("display") != "none";
    }
};
$.CL.Module = function(dom){
    this.dom = dom;
};
$.CL.ModuleLoader = function(dom){
    dom = $(dom);
    if(!dom[0]){return false;}
    if(dom.data("ModuleLoader")){return false;}
    this.dom = dom;
    this.moduleID = "";
    this.module = null;
    this.historys = [];
    this.htmlSource = {};
    this.jsonSource = {};
    this.unified = {};
    this.htmlCache = {};
    this.jsonCache = {};
    this.htmlCacheUpdated = {};
    this.jsonCacheUpdated = {};
    this.htmlRequest = null;
    this.jsonRequest = null;
    this.cacheType = {};
    dom.data("ModuleLoader",this);
};
$.CL.ModuleLoader.prototype = {
    clearJsonCache: function (moduleID) {
        this.jsonCache[moduleID] = null;
        this.jsonCacheUpdated[moduleID] = true;
    },
    clearHtmlCache: function (moduleID) {
        this.htmlCache[moduleID] = null;
        this.htmlCacheUpdated[moduleID] = true;
    },
    changeModule: function (moduleID, htmlSource, jsonSource, cacheType, unified) {
        var othis = this, el;
        if (this.htmlRequest) {
            this.htmlRequest.abort(true);
        }
        if (this.jsonRequest) {
            this.jsonRequest.abort(true);
        }
        if (this.moduleID != moduleID) {
            this.htmlCacheUpdated[moduleID] = true;
        }
        if(!moduleID){
            this._uninstall();
            return true;
        }
        this.unified[moduleID] = unified;
        if (!this.htmlCache[moduleID]) {
            this.cacheType[moduleID] = cacheType || this.cacheType[moduleID] || "dom";
            if (htmlSource instanceof $.CL.Request) {
                //htmlSource.cnet = "iframe";
                //htmlSource.iframe = document.getElementById("module_loader_iframe1");
                var sc = htmlSource.successCallback;
                var ec = htmlSource.errorCallback;
                htmlSource.successCallback = function (data,attach) {
                    othis.htmlRequest = null;
                    data = attach[data];
                    if (othis.cacheType[moduleID] != "code") {
                        othis.htmlCache[moduleID] = $(data)[0];
                    } else {
                        othis.htmlCache[moduleID] = data;
                    }
                    othis.htmlCacheUpdated[moduleID] = true;
                    othis._doChange(moduleID);
                    if(sc && sc != $.UT.DefaultSuccessCallback){
                        sc(data,attach);
                    }
                };
                htmlSource.errorCallback = function (errors, data) {
                    othis.htmlRequest = null;
                    if(ec && ec != $.UT.DefaultErrorCallback){
                        ec(errors, data);
                    }else{
                        $.UT.DefaultErrorCallback(errors, data);
                    }
                };
            }
            this.htmlSource[moduleID] = htmlSource || this.htmlSource[moduleID] || '<div id="' + moduleID + '">new module</div>';
            cacheType = this.cacheType[moduleID];
            htmlSource = this.htmlSource[moduleID];
            if (htmlSource instanceof $.CL.Request) {
                this.htmlRequest = $.UT.GetActionData(htmlSource);
            } else {
                if (cacheType == "code") {
                    if (htmlSource.nodeName) {
                        el = document.createElement("div");
                        el.appendChild(htmlSource);
                        this.htmlCache[moduleID] = el.innerHTML;
                    } else {
                        this.htmlCache[moduleID] = htmlSource;
                    }
                } else {
                    this.htmlCache[moduleID] = ((htmlSource.nodeName) ? htmlSource : $(htmlSource)[0]);
                }
                this.htmlCacheUpdated[moduleID] = true;
            }
        }
        if (!this.jsonCache[moduleID]) {
            if (jsonSource instanceof $.CL.Request) {
                //jsonSource.cnet = "iframe";
                //jsonSource.iframe = document.getElementById("module_loader_iframe2");
                var sc = jsonSource.successCallback;
                var ec = jsonSource.errorCallback;
                jsonSource.successCallback = function (data,attach) {
                    othis.jsonRequest = null;
                    othis.jsonCache[moduleID] = data;
                    othis.jsonCacheUpdated[moduleID] = true;
                    othis._doChange(moduleID);
                    if(sc && sc != $.UT.DefaultSuccessCallback){
                        sc(data,attach);
                    }
                };
                jsonSource.errorCallback = function (errors, data) {
                    othis.jsonRequest = null;
                    if(ec && ec != $.UT.DefaultErrorCallback){
                        ec(errors, data);
                    }else{
                        $.UT.DefaultErrorCallback(errors, data);
                    }
                };
            }
            this.jsonSource[moduleID] = jsonSource || this.jsonSource[moduleID] || {};
            jsonSource = this.jsonSource[moduleID];
            if (jsonSource instanceof $.CL.Request) {
                this.jsonRequest = $.UT.GetActionData(jsonSource);
            } else {
                this.jsonCache[moduleID] = jsonSource;
                this.jsonCacheUpdated[moduleID] = true;
            }
        }
        this._doChange(moduleID);
    },
    isLoading: function(){
        if (this.htmlRequest || this.jsonRequest) {
            return true;
        }else{
            return false;
        }
    },
    goBack: function(n,htmlSource, jsonSource, cacheType, unified){
        this.isGoback = true;
        var id = this.historys[n];
        if(id){
            this.changeModule(id,htmlSource, jsonSource, cacheType, unified);
        }
    },
    _doChange: function (moduleID) {
        if(this.unified[moduleID]){
            if (this.htmlRequest || this.jsonRequest) { return false; } 
        }else{
            if (this.htmlRequest) { return false; }
        }
        var html = this.htmlCache[moduleID], json = this.jsonCache[moduleID];
        if (html && this.htmlCacheUpdated[moduleID]) {
            this._installHtmlCache(moduleID);
        }
        if (json && this.jsonCacheUpdated[moduleID]) {
            this._installJsonCache(moduleID);
        }
        if(!this.jsonCacheUpdated[moduleID] && !this.htmlCacheUpdated[moduleID]){
            this.historys.unshift(moduleID);
            this.historys.length = 20;
            this.module.dom.triggerHandler('expandModule', this.dom[0].id);
            this.dom.triggerHandler('changeModule', moduleID);
        }
    },
    _installHtmlCache: function (moduleID) {
        var html, mod, module;
        html = this.htmlCache[moduleID];
        if (html) {
            this._uninstall();
            if (html.nodeName) {
                this.dom[0].appendChild(html);
                mod = html;
            } else {
                this.dom[0].innerHTML = html;
                mod = this.dom[0].firstChild;
            }
            module = $(mod).data("Module");
            if (!module) {
                module = $(mod).Module();  
                module.parentLoader = this;
            } else {
                if(module.rebind){module.rebind();}
            }
            this.module = module;
            this.moduleID = moduleID;
            this.htmlCacheUpdated[moduleID] = false;
        }

    },
    _installJsonCache: function (moduleID) {
        var json = this.jsonCache[moduleID];
        if (json && this.module.setData) {
            this.module.setData(json);
        }
        this.jsonCacheUpdated[moduleID] = false;
    },
    _uninstall: function () {
        var module = this.module, moduleID = this.moduleID;
        if (module) {
            if(module.unbind){module.unbind();}
            if (this.cacheType[moduleID] != "code") {
                this.htmlCache[moduleID] = this.dom[0].removeChild(this.dom[0].firstChild);
            } else {
                this.htmlCache[moduleID] = this.dom[0].innerHTML;
                this.dom[0].innerHTML = "";
            }
        } else {
            this.dom[0].innerHTML = "";
        }
        this.module = "";
        this.moduleID = "";
    }
};
$.CL.Cps = function(dom, opts){
    this.options = {};
    $.extend(this.options,this.defOptions,opts);
    this.options.id = this.options.id || dom[0].id || "cps";
    this.ajaxTimer = 0;
    this.request = null;
    this.running = 0;
    this.runTimer = 0;
    this.timer = 0;
    this.countdown = 0;
    this.countdownTimer = 0;
    this.netStatus = "";//init,loading,success,error,rest,stop
    this.data = "";
    this.errors = [];
    this.trying = false;
    
};
$.CL.Cps.prototype = {
     defOptions : {
        id: '',
        timeout : 20,
        intervalTime : 5,
        timestamp : 0,
        domain : '',
        channels : {},
        type : 0,
        filter : null,
        autoType : true 
    },
    subscribe : function(channel){
        if (this.options.channels[channel] && this.running) { 
            return true;
        }
        this.options.channels[channel] = true;
        if (!this.runTimer) {
            var _this = this;
            this.runTimer = setTimeout(function () {
                 _this.runTimer = 0;
                _this.run();
            }, 1000);
        }
    },
    delSubscribe : function(channel) {
       if (!this.options.channels[channel]){return true;}
       delete this.options.channels[channel];
        if(this.running){
            if (!this.runTimer) {
                var _this = this;
                this.runTimer = setTimeout(function () {
                     _this.runTimer = 0;
                    _this.run();
                }, 1000);
            }
        }
    },
    run: function (opts) {
        this.abort();
        $.extend(this.options, opts);
        this.running = true;
        this.timer = 0;
        var _this = this;
        if(!this.countdownTimer){
            this.countdownTimer = setInterval(function () {
              _this.countTimer(); 
            }, 1000);
        }
        this.setNetStatus("init");
        if(this.options.type){
            this.sendCps();
        }else{
            this.sendAjax();  
        }
    },
    abort: function(){
        this.running = false;
        this.timer = 0;
        if(this.countdownTimer){clearInterval(this.countdownTimer);this.countdownTimer = 0;}
         if(this.options.type){
            this.dom.unbind('cpsdata');
            this.dom.unbind('cpsconnect');
            //...
        }else{
            if(this.ajaxTimer){clearTimeout(this.ajaxTimer);this.ajaxTimer = 0;}
            if(this.request){this.request.abort();this.request = null;}            
        }
        this.setNetStatus("stop");
    },
    setNetStatus: function(d){
        if(d != this.netStatus){
            this.netStatus = d;
            this.dom.triggerHandler("cpsChange",this);
        }
    },
    countTimer: function(){
       this.countdown = (this.options.intervalTime - this.timer);
       if(this.countdown < 1){this.countdown = 1;}
       this.dom.triggerHandler("cpsTimer",this);
       this.timer ++;
       if(this.netStatus == "success" && this.options.type){this.setNetStatus("rest");}
    },
    soon: function(){
         if(!this.options.type){
            this.run();
        }
    },
    ajaxSuccess : function(data,attach){
        if(!this.running || this.options.type){return false;}
        this.request = null;
        this.data = (this.options.filter)? this.options.filter(data.content) : data.content;
        this.options.timestamp = data.timestamp;
        if($.comet){$.comet.setup({timestamp:data.timestamp});}
        this.setNetStatus("success");
        this.continueAjax();
    },
    ajaxError : function(errors,data){
        if(!this.running || this.options.type){return false;}
        this.request = null;
        this.data = data;
        this.errors = errors;
        this.setNetStatus("error");
        this.continueAjax();
    },
    continueAjax: function(){
        if(!this.running || this.options.type){return false;}
        this.timer = 0;
        this.setNetStatus("rest");
        var _this = this;
        if(!this.ajaxTimer){
            this.ajaxTimer = setTimeout(function () {
            _this.ajaxTimer = 0;
            _this.sendAjax();
            }, this.options.intervalTime*1000);
        }
    },    
    sendAjax: function(){
        var channels = [];
        for(var c in this.options.channels){
            channels.push(c);
        }
        var get = $.extend({channel:channels.join("|"),timestamp:this.options.timestamp},this.options.get);
        var _this = this;
        var opts = {
            module : this.options.id,
            action : "ajax",
            get: get,
            post: this.options.post,
            successCallback : function(data,attach){_this.ajaxSuccess(data,attach);},
            errorCallback : function(errors,data){_this.ajaxError(errors,data);}
        };
        this.request = $.UT.GetActionData(opts);
        this.setNetStatus("loadding");
    },
    sendCps: function(){
        var _this = this;
        var channels = [];
        for(var c in this.options.channels){
                channels.push(c);
            }
        var opts = $.extend({},this.options);
        opts.url = P.Set.ActionMapping[this.options.id]["cps"].url;
        opts.doc = this.dom;
        opts.channel = channels.join("|");
        this.dom.bind('cpsdata', function (e, v, t) {
            _this.cpsSuccess(v, t);
        });
        this.dom.bind('cpsconnect', function (e, d) {
            _this.cpsConnect(d);               
        });
        if(this.trying){
            this.trying = false;
        }else{
            $.comet.run(opts);
        }
        this.setNetStatus("loadding");
    },
    cpsSuccess : function(v, t){
        if(!this.running || !this.options.type){return false;}
        this.data = (this.options.filter)? this.options.filter(v) : v;
        this.options.timestamp = Number(t);
        this.setNetStatus("success");
    },
    cpsError : function(){
        if(!this.running || !this.options.type){return false;}
        this.data = "";
        this.errors = [];
        this.setNetStatus("error");
        if(this.options.autoType){
            this.run({type:0});
            this.tryCps();
        }
    },
    cpsConnect : function(d){
        if(d < 0){
            this.cpsError();
        }
    },
    tryCps: function(){
        var _this = this;
        this.dom.bind('cpsdata', function (e, v, t) {
            _this.tryCpsSuccess(v, t);
        });
    },
    tryCpsSuccess:function(v, t){
        this.trying = true;
        this.run({type:1});
        this.cpsSuccess(v, t);
    }
};
$.CL.GridTable = function(dom, opts){
    dom = $(dom);
    if(!dom[0]){return false;}
    if(dom.data("GridTable")){return false;}
    this.dom = dom;
    this.setOptions(opts);
    this.data = {};
    var that = this;
    this.dom.bind("click",function(e){
        var target = $(e.target);
        var proxy = target.attr("proxy");
        var customerID, actionName, tips;
        if (proxy) {
            target = target.closest("*[dom='" + proxy + "']");
        }
        var action = target.attr("dom");
        switch (action) {
            case "pagination":
                var page = parseInt(target.attr("page"));
                var pagination = that.data.pagination;
                if(isNaN(page)){
                    page = parseInt($("input[dom='pageGoto']",target.parent()).val());
                }
                if(page>0 && page<=pagination.pageTotal && page!=pagination.pageCur){
                    that.loadData({page:page},true);
                }
            return false;
            break;
            case "sort":
                var sort = target.attr("sort");
                var sortType = sort.substr(0,1);
                var sortFields = sort.substr(1);
                that.loadData({sortType:sortType, sortFields:sortFields, page:1},true);
            return false;
            break;
        }
        
    });

};
$.CL.GridTable.prototype = {
    defOptions : {
        "thead" : ["ID"],
        "tbody":  ["id"],
        "cols": [50],
        "align": ["center"],
        "keys": ["id"],
        "width": "50px",
        "source": {},
        "conditions": {},
        "render":null,
        "templete":null
    },
    setOptions: function(opts){
        this.options = {};
        $.extend(this.options,this.defOptions,opts);
        var that = this;
        this.options.source.successCallback = function(data,atta){that.setData(data);};
        if(!this.options.render){this.options.render = this.defRender;}
        if(!this.options.templete){
            var arr=[], i;
            arr.push('{#template MAIN}');
            arr.push('<div class="caption">{$T.caption}</div>');
            arr.push('<table width="'+this.options.width+'"><thead><tr>');
            for(i in this.options.thead){
                 arr.push('<th width="'+this.options.cols[i]+'" align="'+this.options.align[i]+'">'+ this.options.thead[i] +'<a href="#" dom="sort" sort="1'+this.options.tbody[i]+'" class="sort-up">↑</a><a href="#" dom="sort" sort="0'+this.options.tbody[i]+'" class="sort-down">↓</a></th>');
            }
            arr.push('</tr></thead><tbody>');
            arr.push('{#foreach $T.list as r}');
            arr.push('{#include row root=$T.r}');
            arr.push('{#/for}');
            arr.push('</tbody></table>');
            arr.push('<div>总计{$T.pagination.itemTotal}条，每页显示{$T.pagination.itemPage}条，<a dom="pagination" alt="转到第一页" title="转到第一页" href="#" page="1">&lt;&lt;</a> <a dom="pagination" alt="上一页" title="上一页" href="#" page="{$T.pagination.pageCur - 1}">&lt;</a>');
            arr.push('第<input type="text" value="{$T.pagination.pageCur}" size="2" dom="pageGoto"/>页<a dom="pagination" href="#">go</a> / 共{$T.pagination.pageTotal}页');
            arr.push('<a dom="pagination" alt="下一页" title="下一页" href="#" dom="pagination" page="{$T.pagination.pageCur + 1}">&gt;</a> <a dom="pagination" alt="转到最后一页" title="转到最后一页" href="#" page="{$T.pagination.pageTotal}">&gt;&gt;</a></div>');
            arr.push('{#/template MAIN}');
            arr.push('{#template row}');
            arr.push('<tr>');
            for(i in this.options.tbody){
                 arr.push('<td align="'+this.options.align[i]+'">{$T.'+ this.options.tbody[i] +'}</td>');
            }
            arr.push('</tr>');
            arr.push('{#/template row}');
            this.options.templete = arr.join("");
            this.dom.setTemplate(this.options.templete);
        }
    },
    setData : function(data){
        data.pagination.pageTotal = Math.ceil(data.pagination.itemTotal/data.pagination.itemPage);
        this.data = data;
        this.options.render(this.dom,data);
    },
    defRender : function(dom,data){
        dom.processTemplate(data);
    },
    loadData : function(conditions,extend,button){
        if(extend){conditions = $.extend({},this.data.conditions, conditions);}
        this.options.source.post = conditions;
        $.UT.GetActionData(this.options.source);
    }
};
$.CL.Tabs = function(dom, opts){
    dom = $(dom);
    if(!dom[0]){return false;}
    if(dom.data("Tabs")){return false;}
    this.dom = dom;
    this.options = {hoverChange:false, hoverClass:"on"};
    $.extend(this.options,opts);
    this.items = {};
    var othis = this;
    $("li[tab]",dom).each(function(i,o){
        var id = this.getAttribute('tab');
        othis.items[id] = {nav:o,pan:document.getElementById(id)};
        if($(o).hasClass(othis.options.hoverClass)){
            othis.select(id);
        }
        if(othis.options.hoverChange){
            $(o).bind("mouseenter",function(e){
                othis.select(this.getAttribute('tab'));
                return false;
            });
        }else{
            $(o).bind("click",function(e){
                othis.select(this.getAttribute('tab'));
                return false;
            });
        }
    });
    dom.data("Tabs",this);
};
$.CL.Tabs.prototype = {
    select:function(id){
        var item;
        if(this.cur){
            item = this.items[this.cur];
            $(item.nav).removeClass(this.options.hoverClass);
            $(item.pan).hide();
        }
        this.cur = id;
        item = this.items[this.cur];
        $(item.nav).addClass(this.options.hoverClass);
        $(item.pan).show();
        this.dom.triggerHandler('changeTab',id);
    }
};
$.CL.Validator = function(dom,opts){
    dom = $(dom);
    if(!dom[0]){return false;}
    if(dom.data("Validator")){return false;}
    this.dom = dom;
    this.options = {rules:{},singleRule:true,onblur:false,callBack:{initErrors:function(els,rule){},itemError:function(result){},formError:function(result){}},methods:{}};
    var meths = opts.methods;
    delete opts.methods;
    $.extend(this.options,opts);
    $.extend(this.options.methods, this.defaultMethods, meths);
    this.els = $.UT.DomSelector($("input, select, textarea",dom), "vname");
    var othis = this;
    var name;
    var blurHandler = function(e){othis.verify(e.target.getAttribute("vname"));};
    var focusHandler = function(e){othis.prompt(e.target.getAttribute("vname"));};
    for(name in this.options.rules){
        this.options.callBack.initErrors(name, this.els[name], this.options.rules[name]);
        var evts = this.options.rules[name].events || {};
        if(this.options.onblur || evts.onblur){
           $(this.els[name]).bind("blur",blurHandler);
           $(this.els[name]).bind("focus",focusHandler);
        }
    }
    this.dom.data("Validator",this);
};
$.CL.Validator.prototype = {
    formUtil: {
        CheckAble: function (name, form) {
            var element = form[name];
            return (element.type == 'radio' || element.type == 'checkbox');
        },
        GetLength: function (els) {
            if(els[0].nodeName == 'SELECT'){
                return $("option:selected", els[0]).length;
            }else if(els[0].type == "text" || els[0].type == "password" || els[0].nodeName == 'TEXTAREA'){
                return $.trim(els[0].value).length;
            }else{
                return $("input:checked", els).length;
            }
        }
    },
    defaultMethods: {
        required: function (els, param, validator) {
            return $.CL.Validator.prototype.formUtil.GetLength(els) > 0;
        },
        minLength: function (els, param, validator) {
            return $.CL.Validator.prototype.formUtil.GetLength(els) >= param;
        },
        maxLength: function (els, param, validator) {
            return $.CL.Validator.prototype.formUtil.GetLength(els) <= param;
        },
        rangeLength: function (els, param, validator) {
            var length = $.CL.Validator.prototype.formUtil.GetLength(els);
            return (length >= param[0] && length <= param[1]);
        },
        min: function (els, param, validator) {
            return $(els).val() >= param;
        },
        max: function (els, param, validator) {
            return $(els).val() <= param;
        },
        range: function (els, param, validator) {
            var value = $(els).val();
            return (value >= param[0] && value <= param[1]);
        },
        equalTo: function (els, param, validator) {
            var value = $(els).val();
            var ovalue = $(validator.els[param]).val();
            return (value == ovalue);
        },
        notEquqlTo: function (els, param, validator) {
            var value = $(els).val();
            var ovalue = $(validator.els[param]).val();
            return (value != ovalue);
        },
        attribute: function (els, param, validator) {
            var value = $(els).attr(param[0]);
            return (value == param[1]);
        },
        regExp : function(els, param, validator){
            var value = $(els).val();
            return new RegExp(param[0],param[1]).test(value);
        },
        lessThan : function(els, param, validator){
            var value = parseInt($(els).val());
            var ovalue = parseInt($(validator.els[param]).val());
            return (value <= ovalue);
        },
        moreThan : function(els, param, validator){
            var value = parseInt($(els).val());
            var ovalue = parseInt($(validator.els[param]).val());
            return (value >= ovalue);
        },
        isDate: function(els, param, validator) {
            var value = $(els).val();;
            return !/Invalid|NaN/.test(new Date(value));
        },
        isEmail : function(els, param, validator){
            var value = $(els).val();
            return /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
        },
        isHttp: function(els, param, validator){
            var value = $(els).val();
            return /^http:\/\/[\w\./]+\w\/$/i.test(value);
        },
        isNumber: function(els, param, validator){
            var value = $(els).val();
            return /^\d+$/i.test(value);
        }
    },
    validateFields: function (name) {
        var rules = this.options.rules[name];
        var errors;
        var rule;
        var el = this.els[name][0];
        if(el.value !== undefined){
            el.value = $.UT.Trim(el.value);
        }
        for (rule in rules) {
            var method = this.options.methods[rule];
            var data = rules[rule];
            if(!method(this.els[name], data, this)){
                if(!errors){errors = {};}
                errors[rule] = data;
                if(this.options.singleRule){
                    break;
                }
            }
        }
        if(errors){
            return errors;
        }else{
            return true;
        }
    },
    verifyForm: function () {
        var errors;
        var name;
        var ele;
        for (name in this.options.rules) {
            var vdt = this.validateFields(name);
            if(vdt !== true){
                if(!errors){errors = {};}
                errors[name] = vdt;
                if(this.options.singleRule){
                    break;
                }
            }            
        }
        if(errors){
            return errors;
        }else{
            return true;
        }
    },
    verify: function (name,custom) {
        var result;
        if(name){
            result = custom || this.validateFields(name);
            this.options.callBack.itemError(name, result);
        }else{
            result = this.verifyForm();
            this.options.callBack.formError(result);
        }
        return result;
    },
    prompt: function (name) {
        this.options.callBack.itemPrompt(name);
    }
};
$.CL.SimpleValidator = function (dom,opts) {
    this.validatorTooltips = {};
    this.validatorStatus = {};
    this.options = opts || $.UT.JsonDecode(decodeURIComponent(dom.attr("validate")));
    var _this = this;
    this.options.errorMessages = this.options.errorMessages || {};
    this.options.callBack = {
        initErrors : function(name, els, rules){
               var el = els[0];
               var vdtMsg = el.getAttribute("vmessage");
               vdtMsg = vdtMsg || "";
               _this.validatorTooltips[name] = $('<span class="g-vd-tooltip"><q>' + vdtMsg + '</q><i></i></span>').insertBefore(el);
               _this.validatorTooltips[name].attr("prompt",vdtMsg);
               _this.validatorStatus[name] = $('<span class="g-vd-status"></span>').insertAfter(el);
        },
        itemPrompt: function (name) {
            _this.showPrompt(name);
        },
        formError: function (result) {
           var name;
           for (name in _this.validatorTooltips) {
                if (result.hasOwnProperty(name)) {
                    var msgs = [];
                    var lg = _this.options.errorMessages[name];
                    if(lg){
                        for(var ename in result[name]){
                            if(lg[ename]){
                                msgs.push(lg[ename]);
                            }
                        }
                         $("q",_this.validatorTooltips[name][0]).html(msgs.join("；"));
                    }
                    _this.validatorTooltips[name][0].className = "g-vd-tooltip g-vd-error";
                    _this.validatorStatus[name][0].className = "g-vd-status g-vd-s-error";
                } else {
                    _this.validatorTooltips[name][0].className = "g-vd-tooltip";
                    _this.validatorStatus[name][0].className = "g-vd-status";
                }
            }
            return false;
        },
        itemError: function (name, result) {
            if (result===true) {
                _this.validatorTooltips[name][0].className = "g-vd-tooltip";
                _this.validatorStatus[name][0].className = "g-vd-status g-vd-s-pass";
            } else {
                var msgs = [];
                var lg = _this.options.errorMessages[name];
                if(lg){
                    for(var ename in result){
                        if(lg[ename]){
                            msgs.push(lg[ename]);
                        }
                    }
                    $("q",_this.validatorTooltips[name][0]).html(msgs.join("；"));
                }
                _this.validatorTooltips[name][0].className = "g-vd-tooltip g-vd-error";
                _this.validatorStatus[name][0].className = "g-vd-status g-vd-s-error";
            }
            return false;
        }
    };
    this.validator = new $.CL.Validator(dom, this.options);
    if(this.options.autoHide){
        dom.bind("click", function (e) {
            var tag = e.target.nodeName;
            if (tag != "INPUT" && tag != "SELECT" && tag != "TEXTAREA") {
                _this.hideTips(name);
            }
        });
    }
};
$.CL.SimpleValidator.prototype = {
    verifyForm: function () {
        return this.validator.verify();
    },
    showPrompt: function (name) {
        if (name){
            var msg = this.validatorTooltips[name].attr("prompt");
            if(msg){
                this.validatorTooltips[name][0].className = "g-vd-tooltip g-vd-prompt";
                this.validatorStatus[name][0].className = "g-vd-status";
                $("q",this.validatorTooltips[name][0]).html(msg);
            }
        } else {
            for (name in this.validatorTooltips) {
                var msg = this.validatorTooltips[name].attr("prompt");
                if(msg){
                    this.validatorTooltips[name][0].className = "g-vd-tooltip g-vd-prompt";
                    this.validatorStatus[name][0].className = "g-vd-status";
                    $("q",this.validatorTooltips[name][0]).html(msg);
                }
            }
        } 
    },
    customItemErrors: function(name,custom){
        this.validator.verify(name,custom);
    },
    hideTips: function (name) {
        if (name) {
             this.validatorTooltips[name][0].className = "g-vd-tooltip";
        } else {
            for (name in this.validatorTooltips) {
                this.validatorTooltips[name][0].className = "g-vd-tooltip";
            }
        }
    },
    hideIco: function (name) {
        if (name) {
             this.validatorStatus[name][0].className = "g-vd-status";
        } else {
            for (name in this.validatorTooltips) {
                this.validatorStatus[name][0].className = "g-vd-status";
            }
        }
    }
};
$.CL.AutoCompletePickerLayer = function(dom,opts){
    dom = $(dom);
    if(!dom[0]){return false;}
    if(dom.data("AutoCompletePickerLayer")){return false;}
    this.dom = dom;
    if(!opts.rendererItem){opts.rendererItem = $.CL.AutoCompletePickerLayer.prototype.rendererItem;}
    $.CL.Dialog.call(this,dom,opts);    
    this.rendererItem = this.options.rendererItem;
    this.AutoCompleteList = $("*[dom='picker-list']",dom);
    dom.data("AutoCompletePickerLayer",this);
};
$.CL.AutoCompletePickerLayer.prototype = new $.CL.Dialog();
$.CL.AutoCompletePickerLayer.prototype.setData = function(data){
    var keyword = data.term;
    var arr = data.list;
    var html = '';
    for(var i in arr){
        var item = this.rendererItem(arr[i],keyword);
        html += item;
    }
    this.AutoCompleteList.html(html);
};
$.CL.AutoCompletePickerLayer.prototype.rendererItem = function(item,keyword){
    var html = '<li ac-item="'+item.text+'" value="'+item.value+'"><a href="#" class="clearfix"><em>'+item.text.replace(keyword,"<strong>"+keyword+"</strong>")+'</em><span>'+item.note+'</span></a></li>';
    return html;
};
$.CL.AutoComplete = function(dom,opts){
    dom = $(dom);
    if(!dom[0]){return false;}
    if(dom.data("AutoComplete")){return false;}
    this.dom = dom;
    this.options = {minLength:3,pickerLayer:null,rewrite:true,loadingClass:"g-loading-input",request:null,rendererItem:null,offset:{left:0,right:0}};
    $.extend(this.options,opts);
    this.pickerLayer = $(this.options.pickerLayer).Widget("AutoCompletePickerLayer",{mask:false,offset:opts.offset});
    this.loading = false;
    var othis = this;
    $.UT.DefValue(dom);
    this.options.request.successCallback = function(data){othis.successCallback(data);};
    this.options.request.errorCallback = function(errors){othis.errorCallback(errors);};
    dom.bind("keyup",function(e){
        var str = $.trim(e.target.value);
        if(!othis.loading && str.length>=othis.options.minLength){
            othis.loading = true;
            $(this).addClass(othis.options.loadingClass);
            $.UT.GetActionData(othis.options.request);
        }
    });
    if(this.options.rewrite){
        this.pickerLayer.body.bind("click",function(e){
            othis.onPicker($(e.target));
        });
    }
    dom.data("AutoComplete",this);
};
$.CL.AutoComplete.prototype.successCallback = function(data){
    this.loading = false;
    this.dom.removeClass(this.options.loadingClass);
    this.pickerLayer.setData(data);
    this.pickerLayer.open(this.dom);
    G.PupExpandList.push(this.pickerLayer);
};
$.CL.AutoComplete.prototype.errorCallback = function(errors){
    this.loading = false;
    this.dom.removeClass(this.options.loadingClass);
};
$.CL.AutoComplete.prototype.onPicker = function(target){
   var li = target.closest("li",this.pickerLayer.body);
    if(!li[0]){
        li = target.closest("tr",this.pickerLayer.body);
    }
    if(li[0]){
        var text = li.attr("ac-item");
        if(text){
           this.pickerLayer.close();
           this.dom[0].value = text;
           return false; 
        }
    }
};
$.UT.DefValue = function(input){
    if(input.attr("dvalue")){
        input.bind("focus",function(e){
            if($.trim(e.target.value) == e.target.getAttribute("dvalue")){
                e.target.value = "";
            }
        });
        input.bind("blur",function(e){
            if($.trim(e.target.value) == ""){
                e.target.value = e.target.getAttribute("dvalue");
            }
        });
        input.val(input.attr("dvalue"));
    }
};
$.UT.GetActionData = function (args) {
    if (args.button) {
        args.button = $(args.button);
        if (args.button.hasClass(G.LoadingCss)) {
            return false;
        } else {
            args.button.addClass(G.LoadingCss);
        }
    }
    var mp = P.Set.ActionMapping[args.module][args.action],request,queue;
    if(mp.url){args.url = mp.url;}
    if(mp.hasOwnProperty("mergeKey")){
        args.mergeKey = mp.mergeKey;
    }
    if (typeof (args.post) == "function") {
        args.post = args.post();
    }
    if (typeof (args.get) == "function") {
        args.get = args.get();
    }
    if (typeof (args.post) == "string") {
        args.post = $.UT.UnParam(args.post);
    }
    if (typeof (args.get) == "string") {
        args.get = $.UT.UnParam(args.get);
    }
    if (mp.post) {
        args.post = mp.post(args.post);
    }
    if (mp.get) {
        args.get = mp.get(args.get);
    }
    request = new $.CL.Request(args);
    request.cnet = request.cnet.toLowerCase();
    request.method = ((request.post) ? "post" : "get");
    
    if(G.RequestQueue[request.url]){
        if(request.mergeKey){
            G.RequestQueue[args.url].merge[request.mergeKey] = request;
            request = G.RequestQueue[args.url];
        }else{
            return false;
        }
    }else{
        G.RequestQueue[request.url] = request;
    }
    if(!G.RequestTimmer){
        G.RequestTimmer = setTimeout(function(){
            var i;
            G.RequestTimmer = 0;
            for(i in G.RequestQueue){
                $.UT.GetRemoteData(G.RequestQueue[i]);
            }
            G.RequestQueue = {};
        },500);
    }
    return request;
};
$.UT.GetRemoteData = function (request) {
    if(request.globalLoading){
        $.UT.GlobalLoading(true, request.globalLoadingMask);
    }
    var iframeCallBack,key, post, html,i,merge;
    //注意：request会extend $.ajax 中的ajaxSetup，所以key不能与其相同，否则会覆盖
    merge = request.mergeKey;
    for(i in request.merge){
        merge += ","+request.merge[i].mergeKey;
        $.extend(request.get, request.merge[i].get);
        $.extend(request.post, request.merge[i].post);
        request.iframe = request.iframe || request.merge[i].iframe;
        request.iform = request.iform || request.merge[i].iform;
    }
    request.url = request.url + ((request.url.indexOf("?") > -1) ? "&" : "?") + ((request.get) ? $.param(request.get)+'&' : '') + ((merge!=="") ? "___="+merge+'&' : "");
    
    if (request.cnet == "iframe") {
        if(!request.cache){
            request.url = request.url + "&_="+new Date().getTime();
        }
        if (!request.iframe) {
            request.net = document.createElement("iframe"); //$('<iframe></iframe>').appendTo(document.body);
            request.net.style.display = "none";
            request.net.id = "cnet_iframe_" + $.UT.AutoNumber();
            request.net.name = request.net.id;
            document.body.appendChild(request.net);
            window.frames[request.net.id].name = request.net.id; //ie hack;
        } else {
            request.net = request.iframe;
        }
        iframeCallBack = function(o,r){
            o.onload = null;
            o.onreadystatechange = null;
            o.abort = null;
            if (r.button) {
                r.button.removeClass(G.LoadingCss);
            }
            if(r.globalLoading){
                $.UT.GlobalLoading(false);
            }
            setTimeout(function () {
                if (!r.iframe && r.net) {
                    r.net.parentNode.removeChild(r.net);
                }
                if (!r.iform && r.netForm) {
                    r.netForm.parentNode.removeChild(r.netForm);
                }
                r.netForm = null;
                r.net = null;
            }, 100);
        };
        request.net.abort = function (e) {
            var result, mp;
            result = new $.CL.Result();
            result.setErrors([{nid:'framework', eid:'requestAbort', file:'mdf-full.js', line:0 , note:'$.UT.GetRemoteData'}]);
            mp = P.Set.ActionMapping[request.module][request.action];
            if (result.state && mp.result) { result.data = mp.result(result.data); }
            if (!result.state && mp.error) { result.data = mp.error(result.data); }
            request.resultCall(result);
            iframeCallBack(this,request);
        };
        request.net.onload = request.net.onreadystatechange = function (e) {
            var data, result, mp, domain;
            if (this.readyState && this.readyState != "complete") {
                return false;
            }
            domain = "";
            try {
                domain = this.contentWindow.document.domain;
            } catch (e) { }
            if (document.domain == domain) {
                data = this.contentWindow.document.body.innerHTML;
                result = new $.CL.Result(data);
            } else {
                result = new $.CL.Result();
                result.setErrors([{nid:'framework', eid:'crossDomain', file:'mdf-full.js', line:0 , note:'$.UT.GetRemoteData'}]);
            }
            mp = P.Set.ActionMapping[request.module][request.action];
            if (result.state && mp.result) { result.data = mp.result(result.data); }
            if (!result.state && mp.error) { result.data = mp.error(result.data); }
            request.resultCall(result);
            iframeCallBack(this,request);
        };
        if (request.method == "post") {
            post = request.post;
            if (!request.iform) {
                request.netForm = document.createElement("form");
                request.netForm.target = request.net.id;
                request.netForm.style.display = "none";
                html = "";
                for (key in post) {
                    html += '<input type="hidden" name="' + key + '" value="' + post[key] + '"/>';
                }
                request.netForm.innerHTML = html;
                document.body.appendChild(request.netForm);
            } else {
                request.netForm = request.iform;
            }
            for (key in post) {
                html = "";
                if (request.netForm[key] && request.netForm[key].nodeName) {
                    request.netForm[key].value = post[key];
                } else {
                    html += '<input type="hidden" name="' + key + '" value="' + post[key] + '"/>';
                }
                if (html != "") {
                    request.netForm.innerHTML += html;
                }
            }
            request.netForm.action = request.url + "__=iframe";
            request.netForm.method = "post";
            request.netForm.target = request.net.name;
            request.netForm.submit();
        } else {
            request.net.src = request.url + "__=iframe";
        }
        if(request.timeoutTimer){clearInterval(request.timeoutTimer);}
        request.timeBegin = new Date().getTime();
        request.timeoutTimer = setInterval(function(){
            var time = new Date().getTime();
            if((time-request.timeBegin) > request.timeout){request.abort();}
        },1000);
        
    } else {
        request.net = $.ajax({ type: request.method, url: request.url + "__=ajax", data: request.post, timeout: request.timeout, cache: request.cache,
            success: function (data, textStatus) {
                var result, mp;
                if (request.button) {
                    request.button.removeClass(G.LoadingCss);
                }
                if(request.globalLoading){
                    $.UT.GlobalLoading(false);
                }
                result = new $.CL.Result(data);
                mp = P.Set.ActionMapping[request.module][request.action];
                if (result.state && mp.result) { result.data = mp.result(result.data); }
                if (!result.state && mp.error) { result.data = mp.error(result.data); }
                request.resultCall(result);
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                var result, mp;
                //textStatus:"success", "notmodified", "error", "timeout", "abort", or "parsererror"
                if (request.button) {
                    request.button.removeClass(G.LoadingCss);
                }
                if(request.globalLoading){
                    $.UT.GlobalLoading(false);
                }
                result = new $.CL.Result();
                result.setErrors([{nid:'framework', eid:'remoteError', file:'mdf-full.js', line:0 , note:'$.UT.GetRemoteData'}]);
                mp = P.Set.ActionMapping[request.module][request.action];
                if (result.state && mp.result) { result.data = mp.result(result.data); }
                if (!result.state && mp.error) { result.data = mp.error(result.data); }
                request.resultCall(result);
            }
        });
    }
};
$.UT.AutoNumber = function () {
    G.AutoNumber ++;
    return G.AutoNumber;
};
$.UT.Trim = function (t) {
    return $.trim(t);
};
$.UT.HtmlEncode = function (t) {
    if (typeof t == 'string') {
        t = t.replace(RegExp(/>/g), '&gt;');
        t = t.replace(RegExp(/</g), '&lt;');
    }
    return t;
};
$.UT.HtmlDecode = function (t) {
    if (typeof t == 'string') {
        t = t.replace(RegExp(/&gt;/g), '>');
        t = t.replace(RegExp(/&lt;/g), '<');
    }
    return t;
};
$.UT.CreateRequest = function(opts){
    return new $.CL.Request(opts);
};
$.fn.Widget = function(s,opts){
    if(!this[0]){return null;}
    var ins = this.data(s);
     if(ins){
        return ins;
    }else{
        ins = new $.CL[s](this,opts);
        this.data(s, ins);
        ins.dom = this;
        return ins;
    }
};
$.fn.Module = function(s,opts){
    if(!this[0] || !this[0].id){ return null;}
    var ins = this.data("Module");
     if(ins){
        return ins;
    }else{
        var o;
        if(typeof s == "string"){
            o = P.Mod[s];
        }else if(typeof s == "function"){
            o = s;
        }else{
            o = P.Mod[this[0].id] || P.Mod[this.attr("module")];
        }
        o = o || $.CL.Module;
        ins = new o(this,opts);
        this.data("Module", ins);
        ins.dom = this;
        ins.id = this[0].id;
        return ins;
    }
};

$.UT.DomSelector = function (els, attr) {
    var dlist = {},key,i,k;
    attr = attr || "dom";
    for(i=0,k=els.length;i<k;i++){
        key = els[i].getAttribute(attr);
         if (key) {
            if (dlist[key]) {
                dlist[key].push(els[i]);
            } else {
                dlist[key] = [els[i]];
            }
        }
    }
    return dlist;
};
$.UT.InContainer = function(target, container) {
    var parent = target;
    while (parent != document.body) {
        if (parent == container) {
            return true;
        } else {
            parent = parent.parentNode;
        }
    }
    return false;
};
$.UT.MappingKey = function (object, mapping) {
    var type = typeof object, data, i;
    if (type == 'object') {
        if (Array == object.constructor) {
            data = [];
        } else {
            data = {};
        }
        for (i in object) {
            if (mapping[i]) {
                data[mapping[i]] = $.UT.MappingKey(object[i], mapping);
            } else {
                data[i] = $.UT.MappingKey(object[i], mapping);
            }
        }
    } else {
        data = object;
    }
    return data;
};
$.UT.GetModuleContent = function (s) {
    var re, arr;
    re = /<div([\s\S]*?)>([\s\S]*)<\/div>/i;
    arr = re.exec(s);
    return arr[2];
};
$.UT.FillFields = function (els, data, disabled) {
    var key, i, el, tls, disb, tagName, value, k, ii, iilen, tmp, len;
    disabled = disabled || {};
    for (key in disabled) {
        tls = els[key];
        disb = disabled[key];
        if (tls) {
            for (i in tls) {
                el = tls[i];
                tagName = el.tagName.toLowerCase();
                switch (tagName) {
                    case 'input':
                        el.disabled = disb;
                        break;
                    case 'textarea':
                        el.disabled = disb;
                        break;
                    case 'select':
                        el.disabled = disb;
                        break;
                    default:
                        if (disb) {
                            $(el).addClass("disabled");
                        } else {
                            $(el).removeClass("disabled");
                        }
                }
            }
        }
    }
    for (key in data) {
        value = data[key];
        tls = els[key];
        if (tls) {
            for (i in tls) {
                el = tls[i];
                tagName = el.tagName.toLowerCase();
                switch (tagName) {
                    case 'a':
                        el.href = value;
                        break;
                    case 'textarea':
                        el.value = $.UT.HtmlDecode(value);
                        break;
                    case 'select':
                        $(el).val(value);
                        break;
                    case 'input':
                        switch (el.type) {
                            case 'radio':
                                el.checked = (el.value == value) ? true : false;
                                break;
                            case 'checkbox':
                                if (typeof value != 'object') {
                                    el.checked = (el.value == value) ? true : false;
                                } else {
                                    if (!value) { value = []; }
                                    tmp = false;
                                    for (i = 0, len = value.length; i < len; i++) {
                                        if (el.value == value[i]) { tmp = true; break; }
                                    }
                                    el.checked = tmp;
                                }
                                break;
                            default:
                                el.value = $.UT.HtmlDecode(value);
                                break;
                        }
                        break;
                    default:
                        el.innerHTML = value;
                }
            }
        }
    }
};

$.UT.Param = function(object){
    return  decodeURIComponent($.param(object));
};
$.UT.UnParam = function (params) {
    params = decodeURIComponent(params);
    var data = {};
    var su = false;
    params.replace(/([^?=&]+)=([^&#]*)/g, function (m, key, value) {
        su = true;
        data[key] = value;
    });
    return (su)?data:null;
};
$.UT.JsonDecode = function (strJson, reviver) {
    //return $.parseJSON(strJson);
    //return JSON.parse(strJson, reviver);
    try {
        var obj = eval("(" + strJson + ")");
    } catch (e) {
        return null;
    }
    return obj;
};
$.UT.JsonEncode = function (value, replacer, space) {
    return JSON.stringify(value, replacer, space);
};
$.UT.Alert = function(text, title, confirm){
    alert(text);
};
$.UT.DefaultSuccessCallback = function(data,attach){
    $.UT.Alert(data);
};
$.UT.DefaultErrorCallback = function(errors,data){
    var s='', i, error, msg;
    for (i in errors) {
        error = errors[i];
        msg = P.Set.Errors[error.eid];
        s += '('+error.eid+')' + msg + "\n" + "file:" + error.file + "\n" + "line:" + error.line + "\n" + "note:" + error.note; 
    }
    $.UT.Alert(s);
};
$.UT.FormatString = function (source, params, splitter) {
    if(!splitter){splitter = ["{","}"];}
    var re = new RegExp("\\"+splitter[0]+"([^\\"+splitter[0]+"\\"+splitter[1]+"]*)\\"+splitter[1],"g");
    var subReplace = function (template, o) {
        return template.replace(re, function (a, b) {
            var r = o[b];
            return (r !== undefined) ? r : a;
        }
        );
    };
    if (re.test(source)) { source = subReplace(source, params); }
    return source;
};
$.UT.GlobalLoading = function(show, mask){
    if (!(G.GlobalLoading instanceof $.CL.Dialog)){
        G.GlobalLoading = $(G.GlobalLoading).Widget("Dialog");
    }
    if(show){
        G.GlobalLoadingCounter ++;
    }else{
        G.GlobalLoadingCounter --;
    }
    if(G.GlobalLoadingCounter){
        G.GlobalLoading.open("fixed", mask);
    }else{
        G.GlobalLoading.close();
    }
};
$.UT.Templetes = function(dom){
    var templetes = $.UT.DomSelector($("div,tbody", dom), "templete");
    var templeteEls = $.UT.DomSelector($("textarea", dom), "templete");
    for (var i in templetes) {
        if (templeteEls[i]) {
            $(templetes[i]).setTemplate(templeteEls[i][0].value);
        }
    }
    return templetes;
};
$.UT.Cookie = function(name, value, options) {
    if (typeof value != 'undefined') { // name and value given, set cookie
        options = options || {};
        if (value === null) {
            value = '';
            options = $.extend({}, options); // clone object since it's unexpected behavior if the expired property were changed
            options.expires = -1;
        }
        var expires = '';
        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
            var date;
            if (typeof options.expires == 'number') {
                date = new Date();
                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
            } else {
                date = options.expires;
            }
            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
        }
        // NOTE Needed to parenthesize options.path and options.domain
        // in the following expressions, otherwise they evaluate to undefined
        // in the packed version for some reason...
        var path = options.path ? '; path=' + (options.path) : '';
        var domain = options.domain ? '; domain=' + (options.domain) : '';
        var secure = options.secure ? '; secure' : '';
        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
    } else { // only name given, get cookie
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            var i;
            for (i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
};